// XML Processing (XML处理) 示例
// 演示 Pascal 中XML处理的各种用法
program p_49_xml_processing;

{$mode objfpc}{$H+}
// {$mode objfpc} 启用 Object Pascal 模式
// {$H+} 启用长字符串支持（AnsiString）

// 引入单元文件
uses
  SysUtils,        // 系统工具单元
  Classes,         // 类单元
  DOM,             // DOM处理单元
  XMLRead,         // XML读取单元
  XMLWrite;        // XML写入单元

// XML文档的创建和基本操作示例
procedure CreateAndManipulateXMLDocument;
var
  xmlDoc: TXMLDocument;
  rootElement: TDOMElement;
  childElement: TDOMElement;
  textNode: TDOMText;
  xmlString: String;
  stringStream: TStringStream;
begin
  WriteLn('1. XML文档的创建和基本操作:');
  
  // 创建XML文档
  xmlDoc := TXMLDocument.Create;
  try
    // 创建根元素
    rootElement := xmlDoc.CreateElement('library');
    xmlDoc.AppendChild(rootElement);
    
    // 创建子元素
    childElement := xmlDoc.CreateElement('book');
    rootElement.AppendChild(childElement);
    
    // 添加属性
    childElement.SetAttribute('id', '1');
    childElement.SetAttribute('category', 'fiction');
    
    // 添加子元素和文本内容
    var titleElement := xmlDoc.CreateElement('title');
    childElement.AppendChild(titleElement);
    textNode := xmlDoc.CreateTextNode('《Pascal编程指南》');
    titleElement.AppendChild(textNode);
    
    var authorElement := xmlDoc.CreateElement('author');
    childElement.AppendChild(authorElement);
    textNode := xmlDoc.CreateTextNode('张三');
    authorElement.AppendChild(textNode);
    
    var priceElement := xmlDoc.CreateElement('price');
    childElement.AppendChild(priceElement);
    textNode := xmlDoc.CreateTextNode('59.99');
    priceElement.AppendChild(textNode);
    
    // 转换为字符串
    stringStream := TStringStream.Create('');
    try
      WriteXMLFile(xmlDoc, stringStream);
      xmlString := stringStream.DataString;
      WriteLn('  创建的XML文档:');
      WriteLn('    ', StringReplace(xmlString, LineEnding, '', [rfReplaceAll]));
    finally
      stringStream.Free;
    end;
  finally
    xmlDoc.Free;
  end;
end;

// XML元素的添加和修改示例
procedure AddAndModifyXMLElements;
var
  xmlDoc: TXMLDocument;
  rootElement: TDOMElement;
  bookElement: TDOMElement;
  stringStream: TStringStream;
begin
  WriteLn('2. XML元素的添加和修改:');
  
  // 创建XML文档
  xmlDoc := TXMLDocument.Create;
  try
    // 创建根元素
    rootElement := xmlDoc.CreateElement('students');
    xmlDoc.AppendChild(rootElement);
    
    // 添加第一个学生
    var student1 := xmlDoc.CreateElement('student');
    student1.SetAttribute('id', '001');
    rootElement.AppendChild(student1);
    
    var name1 := xmlDoc.CreateElement('name');
    name1.TextContent := '李四';
    student1.AppendChild(name1);
    
    var age1 := xmlDoc.CreateElement('age');
    age1.TextContent := '20';
    student1.AppendChild(age1);
    
    var grade1 := xmlDoc.CreateElement('grade');
    grade1.TextContent := '大二';
    student1.AppendChild(grade1);
    
    // 添加第二个学生
    var student2 := xmlDoc.CreateElement('student');
    student2.SetAttribute('id', '002');
    rootElement.AppendChild(student2);
    
    var name2 := xmlDoc.CreateElement('name');
    name2.TextContent := '王五';
    student2.AppendChild(name2);
    
    var age2 := xmlDoc.CreateElement('age');
    age2.TextContent := '22';
    student2.AppendChild(age2);
    
    var grade2 := xmlDoc.CreateElement('grade');
    grade2.TextContent := '大四';
    student2.AppendChild(grade2);
    
    // 修改元素内容
    age1.TextContent := '21';  // 更新李四的年龄
    
    // 添加新元素
    var major1 := xmlDoc.CreateElement('major');
    major1.TextContent := '计算机科学';
    student1.AppendChild(major1);
    
    var major2 := xmlDoc.CreateElement('major');
    major2.TextContent := '软件工程';
    student2.AppendChild(major2);
    
    stringStream := TStringStream.Create('');
    try
      WriteXMLFile(xmlDoc, stringStream);
      WriteLn('  修改后的XML文档:');
      var lines := stringStream.DataString.Split([LineEnding]);
      for var i := 0 to High(lines) do
        if lines[i] <> '' then
          WriteLn('    ', lines[i]);
    finally
      stringStream.Free;
    end;
  finally
    xmlDoc.Free;
  end;
end;

// XML文档的解析和读取示例
procedure ParseAndReadXMLDocument;
var
  xmlDoc: TXMLDocument;
  stringStream: TStringStream;
  xmlContent: String;
begin
  WriteLn('3. XML文档的解析和读取:');
  
  // 创建示例XML内容
  xmlContent := '<?xml version="1.0" encoding="UTF-8"?>' + LineEnding +
                '<products>' + LineEnding +
                '  <product id="1" category="electronics">' + LineEnding +
                '    <name>智能手机</name>' + LineEnding +
                '    <price>2999.99</price>' + LineEnding +
                '    <stock>50</stock>' + LineEnding +
                '  </product>' + LineEnding +
                '  <product id="2" category="books">' + LineEnding +
                '    <name>Pascal编程实战</name>' + LineEnding +
                '    <price>79.99</price>' + LineEnding +
                '    <stock>100</stock>' + LineEnding +
                '  </product>' + LineEnding +
                '</products>';
  
  WriteLn('  原始XML内容:');
  var lines := xmlContent.Split([LineEnding]);
  for var i := 0 to High(lines) do
    if lines[i] <> '' then
      WriteLn('    ', lines[i]);
  
  // 解析XML
  stringStream := TStringStream.Create(xmlContent);
  try
    ReadXMLFile(xmlDoc, stringStream);
    try
      WriteLn('  解析结果:');
      
      // 获取根元素
      var root := xmlDoc.DocumentElement;
      WriteLn('    根元素: ', root.NodeName);
      
      // 遍历产品元素
      var productList := root.ChildNodes;
      for var i := 0 to productList.Count - 1 do
      begin
        var product := productList.Item[i];
        if product.NodeType = ELEMENT_NODE then
        begin
          WriteLn('    产品 ', i + 1, ':');
          WriteLn('      ID: ', (product as TDOMElement).GetAttribute('id'));
          WriteLn('      类别: ', (product as TDOMElement).GetAttribute('category'));
          
          // 获取子元素
          for var j := 0 to product.ChildNodes.Count - 1 do
          begin
            var child := product.ChildNodes.Item[j];
            if child.NodeType = ELEMENT_NODE then
              WriteLn('      ', child.NodeName, ': ', child.TextContent);
          end;
        end;
      end;
    finally
      xmlDoc.Free;
    end;
  finally
    stringStream.Free;
  end;
end;

// XML属性处理示例
procedure XMLAttributeHandling;
var
  xmlDoc: TXMLDocument;
  stringStream: TStringStream;
begin
  WriteLn('4. XML属性处理:');
  
  // 创建带属性的XML
  xmlDoc := TXMLDocument.Create;
  try
    var root := xmlDoc.CreateElement('configuration');
    xmlDoc.AppendChild(root);
    
    // 创建带多个属性的元素
    var server := xmlDoc.CreateElement('server');
    server.SetAttribute('name', 'web-server-01');
    server.SetAttribute('ip', '192.168.1.100');
    server.SetAttribute('port', '8080');
    server.SetAttribute('enabled', 'true');
    root.AppendChild(server);
    
    // 创建另一个带属性的元素
    var database := xmlDoc.CreateElement('database');
    database.SetAttribute('type', 'mysql');
    database.SetAttribute('host', 'localhost');
    database.SetAttribute('port', '3306');
    database.SetAttribute('username', 'admin');
    database.SetAttribute('password', 'secret');
    root.AppendChild(database);
    
    stringStream := TStringStream.Create('');
    try
      WriteXMLFile(xmlDoc, stringStream);
      WriteLn('  带属性的XML:');
      var lines := stringStream.DataString.Split([LineEnding]);
      for var i := 0 to High(lines) do
        if lines[i] <> '' then
          WriteLn('    ', lines[i]);
    finally
      stringStream.Free;
    end;
    
    // 读取属性
    WriteLn('  属性读取结果:');
    var serverElement := root.ChildNodes.Item[0] as TDOMElement;
    WriteLn('    服务器名称: ', serverElement.GetAttribute('name'));
    WriteLn('    IP地址: ', serverElement.GetAttribute('ip'));
    WriteLn('    端口: ', serverElement.GetAttribute('port'));
    WriteLn('    是否启用: ', serverElement.GetAttribute('enabled'));
    
    var dbElement := root.ChildNodes.Item[1] as TDOMElement;
    WriteLn('    数据库类型: ', dbElement.GetAttribute('type'));
    WriteLn('    主机: ', dbElement.GetAttribute('host'));
    WriteLn('    数据库端口: ', dbElement.GetAttribute('port'));
    WriteLn('    用户名: ', dbElement.GetAttribute('username'));
  finally
    xmlDoc.Free;
  end;
end;

// 复杂XML结构的处理示例
procedure ComplexXMLStructureHandling;
var
  xmlDoc: TXMLDocument;
  stringStream: TStringStream;
  xmlContent: String;
begin
  WriteLn('5. 复杂XML结构的处理:');
  
  // 创建复杂的嵌套XML
  xmlContent := '<?xml version="1.0" encoding="UTF-8"?>' + LineEnding +
                '<company>' + LineEnding +
                '  <name>科技有限公司</name>' + LineEnding +
                '  <departments>' + LineEnding +
                '    <department id="dev" name="开发部">' + LineEnding +
                '      <employees>' + LineEnding +
                '        <employee id="001">' + LineEnding +
                '          <name>张三</name>' + LineEnding +
                '          <position>高级工程师</position>' + LineEnding +
                '          <salary>15000</salary>' + LineEnding +
                '          <skills>' + LineEnding +
                '            <skill>Pascal</skill>' + LineEnding +
                '            <skill>Python</skill>' + LineEnding +
                '            <skill>JavaScript</skill>' + LineEnding +
                '          </skills>' + LineEnding +
                '        </employee>' + LineEnding +
                '        <employee id="002">' + LineEnding +
                '          <name>李四</name>' + LineEnding +
                '          <position>初级工程师</position>' + LineEnding +
                '          <salary>8000</salary>' + LineEnding +
                '          <skills>' + LineEnding +
                '            <skill>Python</skill>' + LineEnding +
                '            <skill>Java</skill>' + LineEnding +
                '          </skills>' + LineEnding +
                '        </employee>' + LineEnding +
                '      </employees>' + LineEnding +
                '    </department>' + LineEnding +
                '    <department id="test" name="测试部">' + LineEnding +
                '      <employees>' + LineEnding +
                '        <employee id="003">' + LineEnding +
                '          <name>王五</name>' + LineEnding +
                '          <position>测试工程师</position>' + LineEnding +
                '          <salary>10000</salary>' + LineEnding +
                '          <skills>' + LineEnding +
                '            <skill>自动化测试</skill>' + LineEnding +
                '            <skill>性能测试</skill>' + LineEnding +
                '          </skills>' + LineEnding +
                '        </employee>' + LineEnding +
                '      </employees>' + LineEnding +
                '    </department>' + LineEnding +
                '  </departments>' + LineEnding +
                '</company>';
  
  WriteLn('  复杂XML结构:');
  var lines := xmlContent.Split([LineEnding]);
  for var i := 0 to High(lines) do
    if lines[i] <> '' then
      WriteLn('    ', lines[i]);
  
  // 解析复杂XML
  stringStream := TStringStream.Create(xmlContent);
  try
    ReadXMLFile(xmlDoc, stringStream);
    try
      WriteLn('  解析结果:');
      
      var root := xmlDoc.DocumentElement;
      WriteLn('    公司名称: ', root.ChildNodes.Item[0].TextContent);  // name元素
      
      var departments := root.ChildNodes.Item[1];  // departments元素
      WriteLn('    部门信息:');
      
      for var i := 0 to departments.ChildNodes.Count - 1 do
      begin
        var department := departments.ChildNodes.Item[i];
        if department.NodeType = ELEMENT_NODE then
        begin
          var deptElement := department as TDOMElement;
          WriteLn('      部门ID: ', deptElement.GetAttribute('id'));
          WriteLn('      部门名称: ', deptElement.GetAttribute('name'));
          
          var employees := department.ChildNodes.Item[0];  // employees元素
          WriteLn('      员工列表:');
          
          for var j := 0 to employees.ChildNodes.Count - 1 do
          begin
            var employee := employees.ChildNodes.Item[j];
            if employee.NodeType = ELEMENT_NODE then
            begin
              WriteLn('        员工ID: ', (employee as TDOMElement).GetAttribute('id'));
              
              for var k := 0 to employee.ChildNodes.Count - 1 do
              begin
                var empInfo := employee.ChildNodes.Item[k];
                if empInfo.NodeType = ELEMENT_NODE then
                begin
                  if empInfo.NodeName = 'skills' then
                  begin
                    Write('        技能: ');
                    for var l := 0 to empInfo.ChildNodes.Count - 1 do
                    begin
                      var skill := empInfo.ChildNodes.Item[l];
                      if skill.NodeType = ELEMENT_NODE then
                      begin
                        Write(skill.TextContent);
                        if l < empInfo.ChildNodes.Count - 1 then
                          Write(', ');
                      end;
                    end;
                    WriteLn;
                  end
                  else
                    WriteLn('        ', empInfo.NodeName, ': ', empInfo.TextContent);
                end;
              end;
            end;
          end;
        end;
      end;
    finally
      xmlDoc.Free;
    end;
  finally
    stringStream.Free;
  end;
end;

// XML在实际应用中的使用示例
procedure PracticalXMLApplications;
var
  xmlDoc: TXMLDocument;
  stringStream: TStringStream;
begin
  WriteLn('6. XML在实际应用中的使用:');
  
  // 配置文件处理示例
  WriteLn('  配置文件处理:');
  xmlDoc := TXMLDocument.Create;
  try
    var root := xmlDoc.CreateElement('appSettings');
    xmlDoc.AppendChild(root);
    
    // 应用设置
    var appConfig := xmlDoc.CreateElement('application');
    root.AppendChild(appConfig);
    
    var appName := xmlDoc.CreateElement('name');
    appName.TextContent := 'MyPascalApp';
    appConfig.AppendChild(appName);
    
    var version := xmlDoc.CreateElement('version');
    version.TextContent := '1.0.0';
    appConfig.AppendChild(version);
    
    var debugMode := xmlDoc.CreateElement('debug');
    debugMode.TextContent := 'true';
    appConfig.AppendChild(debugMode);
    
    // 数据库设置
    var dbConfig := xmlDoc.CreateElement('database');
    dbConfig.SetAttribute('type', 'sqlite');
    root.AppendChild(dbConfig);
    
    var dbPath := xmlDoc.CreateElement('path');
    dbPath.TextContent := './data/app.db';
    dbConfig.AppendChild(dbPath);
    
    var dbTimeout := xmlDoc.CreateElement('timeout');
    dbTimeout.TextContent := '30';
    dbConfig.AppendChild(dbTimeout);
    
    // 日志设置
    var logConfig := xmlDoc.CreateElement('logging');
    root.AppendChild(logConfig);
    
    var logLevel := xmlDoc.CreateElement('level');
    logLevel.TextContent := 'info';
    logConfig.AppendChild(logLevel);
    
    var logFile := xmlDoc.CreateElement('file');
    logFile.TextContent := './logs/app.log';
    logConfig.AppendChild(logFile);
    
    stringStream := TStringStream.Create('');
    try
      WriteXMLFile(xmlDoc, stringStream);
      WriteLn('    应用配置XML:');
      var lines := stringStream.DataString.Split([LineEnding]);
      for var i := 0 to High(lines) do
        if lines[i] <> '' then
          WriteLn('      ', lines[i]);
    finally
      stringStream.Free;
    end;
  finally
    xmlDoc.Free;
  end;
  
  WriteLn;
  
  // 数据交换格式示例
  WriteLn('  数据交换格式:');
  xmlDoc := TXMLDocument.Create;
  try
    var root := xmlDoc.CreateElement('dataExchange');
    xmlDoc.AppendChild(root);
    
    root.SetAttribute('timestamp', DateTimeToStr(Now));
    root.SetAttribute('version', '1.0');
    
    // 用户数据
    var users := xmlDoc.CreateElement('users');
    root.AppendChild(users);
    
    for var i := 1 to 3 do
    begin
      var user := xmlDoc.CreateElement('user');
      user.SetAttribute('id', IntToStr(i));
      users.AppendChild(user);
      
      var name := xmlDoc.CreateElement('name');
      name.TextContent := '用户' + IntToStr(i);
      user.AppendChild(name);
      
      var email := xmlDoc.CreateElement('email');
      email.TextContent := 'user' + IntToStr(i) + '@example.com';
      user.AppendChild(email);
      
      var status := xmlDoc.CreateElement('status');
      if i = 1 then
        status.TextContent := 'active'
      else if i = 2 then
        status.TextContent := 'inactive'
      else
        status.TextContent := 'pending';
      user.AppendChild(status);
    end;
    
    stringStream := TStringStream.Create('');
    try
      WriteXMLFile(xmlDoc, stringStream);
      WriteLn('    数据交换XML:');
      var lines := stringStream.DataString.Split([LineEnding]);
      for var i := 0 to High(lines) do
        if lines[i] <> '' then
          WriteLn('      ', lines[i]);
    finally
      stringStream.Free;
    end;
  finally
    xmlDoc.Free;
  end;
end;

// 程序主入口
begin
  WriteLn('=== Pascal XML处理示例 ===');
  WriteLn;
  
  // 1. XML文档的创建和基本操作
  CreateAndManipulateXMLDocument;
  
  WriteLn;
  
  // 2. XML元素的添加和修改
  AddAndModifyXMLElements;
  
  WriteLn;
  
  // 3. XML文档的解析和读取
  ParseAndReadXMLDocument;
  
  WriteLn;
  
  // 4. XML属性处理
  XMLAttributeHandling;
  
  WriteLn;
  
  // 5. 复杂XML结构的处理
  ComplexXMLStructureHandling;
  
  WriteLn;
  
  // 6. XML在实际应用中的使用
  PracticalXMLApplications;
  
  WriteLn;
  WriteLn('演示了 Pascal 中XML处理的各种用法');
  
  // 等待用户按键，防止程序窗口立即关闭
  ReadLn;
end.